home *** CD-ROM | disk | FTP | other *** search
- ;* READATOM.ASM
- ;************************************************************************
- ;* *
- ;* PC Scheme/Geneva 4.00 Borland TASM code *
- ;* *
- ;* (c) 1985-1988 by Texas Instruments, Inc. See COPYRIGHT.TXT *
- ;* (c) 1992 by L. Bartholdi & M. Vuilleumier, University of Geneva *
- ;* *
- ;*----------------------------------------------------------------------*
- ;* *
- ;* Read an atom (interpreter support) *
- ;* *
- ;*----------------------------------------------------------------------*
- ;* *
- ;* Created by: John Jensen Date: 1985 *
- ;* Revision history: *
- ;* - 10 Feb 87: fix to convert first char after # to upper case (tc) *
- ;* - 10 Feb 87: added support to do readline (tc) *
- ;* - 18 Jun 92: Renaissance (Borland Compilers, ...) *
- ;* *
- ;* ``In nomine omnipotentii dei'' *
- ;************************************************************************
- IDEAL
- %PAGESIZE 60, 132
- MODEL medium
- LOCALS @@
-
- INCLUDE "scheme.ash"
- INCLUDE "interprt.ash"
-
- COM EQU 3bh
- BUFSIZE EQU 256
- TEST_NUM EQU 8
- EOFERR EQU 1
- SHARPERR EQU 7
- PORTERR EQU -2
- HEAPERR EQU -3
-
- DATASEG
-
- inv_char DB "Invalid character constant", 0
- limit DW ? ; current size of atom buffer
- main_reg DW ? ; main register
- flg_eof DW ? ; whether to flag end-of-file
- atomb DW ? ; atom buffer
- char DB 20h ; most recently received char
-
- CODESEG
-
- ;************************************************************************
- ; Set up for the operation of reading a single line from the given port.
- ;************************************************************************
- PROC C sread_ln USES si di, @@portreg, @@page, @@disp
- mov ax, [@@portreg]
- mov [main_reg], ax
- call ssetadr C, [@@page], [@@disp]
- or ax, ax
- jz @@portok
- mov ax, PORTERR
- call errmsg C, ax
- jmp @@exit
- @@portok:
- mov [flg_eof], 1
- call rcvchar ; get char, eof won't return here
- jnc @@readok
- jmp @@exit
- @@readok:
- cmp al, LF ; is char linefeed? if so, restart
- je @@portok
- or al, al ; is this the previous EOLN marker ?
- je @@portok
-
- push ax
- mov ax, BUFSIZE ; Get buffer size
- mov [limit], ax
- call malloc C, ax
- or ax, ax
- jne @@allocok
- pop ax ; trash off
- mov ax, HEAPERR
- call abortread C, ax
- jmp @@exit
-
- @@allocok:
- mov si, ax
- mov [atomb], ax ; address of buffer
- mov [flg_eof], 0 ; don't flag error on EOF
- xor bx, bx ; index into buffer
- pop ax
- @@readchar:
- cmp al, CR
- je @@done
- cmp al, CTRL_Z
- je @@done
- cmp al, LF
- je @@done
-
- call addchar C, bx, ax ; Add character to buffer
- or ax, ax
- jnz @@exit
- inc bx
- call rcvchar
- jc @@exit
- jmp @@readchar
-
- @@done:
- mov cx, STRTYPE ; Allocate string data type
- push bx
- call alloc_block C, [main_reg], cx, bx
- mov cx, 3 ; Copy buffer to Scheme string
- mov si, [atomb]
- pop bx
- call toblock C, [main_reg], cx, si, bx
- call free C, [atomb]
- mov [flg_eof], 1 ; Reset flags
- mov [limit], 0
- @@exit:
- ret
- ENDP sread_ln
-
- ;************************************************************************
- ; Set up for the operation of reading a single atom from the given port.
- ; Special characters such as ')' are parsed as lists(!) to tell them from
- ; ordinary atoms.
- ;************************************************************************
- PROC C sread_atom USES si di, @@portreg:WORD, @@page:WORD, @@disp:WORD
- mov ax, [@@portreg]
- mov [main_reg], ax
- call ssetadr C, [@@page], [@@disp]
- or ax, ax
- jz @@portok
- mov ax, PORTERR
- call errmsg C, ax
- jmp @@exit
- @@portok:
- mov [flg_eof], 1
- mov [limit], 0
- @@skipspaces:
- call rcvchar
- jc @@exit
- call ck_space
- or cx, cx
- jz @@skipspaces
- cmp al, ';'
- jne @@dothejob
- @@comment:
- call rcvchar
- jc @@exit
- cmp al, CR
- jne @@comment
- jmp @@skipspaces
- @@dothejob:
- or al, al ; null character?
- jz @@skipspaces
- call read_atom C
- @@exit:
- ret
- ENDP sread_atom
-
- ;************************************************************************
- ; Fetch one character from the input stream
- ;************************************************************************
- PROC rcvchar NEAR
- push bx cx dx
- call take_ch C ; takechar()
- pop dx cx bx
- cmp ax, 256 ; Check the character
- jge @@fail
- cmp al, CTRL_Z ; EOF character?
- je @@fail
- mov [char], al
- clc ; no carry = success
- ret
- @@fail: ; EOF character is fetched
- cmp [flg_eof], 0 ; EOF flag set?
- jne @@error
- mov ax, CTRL_Z
- mov [char], al
- clc ; no carry = success
- ret
- @@error:
- mov ax, EOFERR
- call abortread C, ax
- stc ; carry = defeat
- ret
- ENDP rcvchar
-
- ;************************************************************************
- ; Read in an atom (symbol, string, number)
- ; Store the pointer to the atom in REG.
- ; Special characters such as ')' or ',' are read as atoms themselves.
- ; Normal atoms will end in a whitespace or a terminating macro character;
- ; strings end with the closing '"'.
- ; Numbers in the requested base are interpreted as such.
- ; On exit, the next character in the buffer is the one following the last
- ; character of the atom.
- ;************************************************************************
- PROC C read_atom NEAR
- LOCAL @@biglimit, @@big, @@flo:QWORD, @@escaped, @@char, @@numbase, @@status
-
- mov di, ax ; save the char just read
- xor cx, cx
- mov [flg_eof], cx ; initialization
- mov [@@char], cx
- mov [@@escaped], cx
- mov [@@status], cx
- mov [@@numbase], 10
- mov ax, BUFSIZE
- mov [limit], ax
- call malloc C, ax ; allocate memory
- or ax, ax
- jne @@memok
- @@memerr:
- mov ax, HEAPERR
- call abortread C, ax
- jmp @@ret
- @@memok:
- mov si, ax
- mov [atomb], ax ; save the address of atom buffer
- mov ax, di
- mov di, [main_reg]
- xor bx, bx
- cmp al, '[' ; check for special characters first
- je @@special
- cmp al, ']'
- je @@special
- cmp al, '{'
- je @@special
- cmp al, '}'
- je @@special
- cmp al, '('
- je @@special
- cmp al, ')'
- je @@special
- cmp al, ''''
- je @@special
- cmp al, '`'
- jne @@string
- @@special:
- mov [si], al ; *atomb = ch
- inc bx
- jmp @@donespecial
-
- @@string:
- cmp al, '"'
- jne @@comma
- call delimby C, ax ; get the string
- jnc @@stringend
- jmp @@bye ; eof occured
- @@stringend:
- push bx
- mov cx, STRTYPE
- call alloc_block C, [main_reg], cx, bx
- mov cx, 3
- mov si, [atomb]
- pop bx
- call toblock C, [main_reg], cx, si, bx
- jmp @@bye
-
- @@comma:
- cmp al, ','
- jne @@macro
- mov [si], al
- inc bx
- call rcvchar
- jnc @@commaok
- jmp @@bye
- @@commaok:
- cmp al, '@'
- je @@commaspecial
- cmp al, '.'
- je @@commaspecial
- jmp @@donenormal
- @@commaspecial:
- mov [si+bx], al
- inc bx
- jmp @@donespecial
-
- @@macro:
- cmp al, '#'
- je @@itsamacro
- jmp @@symbol
- @@itsamacro:
- mov [flg_eof], 1
- @@integerloop:
- or bx, bx ; first character?
- jz @@macrofirst
- @@rathersymbol:
- jmp @@alsosymbol
- @@macrofirst:
- cmp al, '#'
- jne @@rathersymbol
- call rcvchar
- jnc @@macrook
- jmp @@bye
- @@macrook:
- call ck_space
- or cx, cx
- jnz @@macrostillok
- @@macroerror:
- mov ax, SHARPERR
- call abortread C, ax
- jmp @@bye
- @@macrostillok:
- mov [si+1], al ; save the character
- push bx
- lea bx, [locases]
- xlat
- pop bx
- cmp al, 'b'
- jne @@decimal
- mov [@@numbase], 2
- jmp @@nextinteger
- @@decimal:
- cmp al, 'd'
- jne @@hexadecimal
- mov [@@numbase], 10
- jmp @@nextinteger
- @@hexadecimal:
- cmp al, 'x'
- je @@itsahex
- cmp al, 'h'
- jne @@octal
- @@itsahex:
- mov [@@numbase], 16
- jmp @@nextinteger
- @@octal:
- cmp al, 'o'
- jne @@donebase
- mov [@@numbase], 8
- jmp @@nextinteger
-
- @@donebase:
- cmp al, '\'
- jne @@modifier
- call rcvchar
- jnc @@baseok
- @@baseerror:
- jmp @@bye
- @@baseok:
- call addchar C, bx, ax
- or ax, ax
- jnz @@baseerror
- inc bx
- mov [@@char], 1
- mov [@@escaped], 1
- jmp @@nextinteger
-
- @@modifier:
- cmp al, 'i'
- je @@nextinteger
- cmp al, 'e'
- je @@nextinteger
- cmp al, 's'
- je @@nextinteger
- cmp al, 'l'
- je @@nextinteger
- cmp al, '<'
- je @@tomacroerror
- cmp al, ')'
- jne @@modifierok
- @@tomacroerror:
- jmp @@macroerror
- @@modifierok:
- mov [BYTE si], '#'
- lea bx, [hicases]
- xlat
- mov [si+1], al ; Change letter past # to upper case
- mov bx, 2
- cmp al, '('
- jne @@nextinteger
- jmp @@donespecial
- @@nextinteger:
- call rcvchar
- jnc @@integerok
- jmp @@bye
- @@integerok:
- jmp @@integerloop
-
- @@alsosymbol:
- mov [flg_eof], 0
- @@symbol:
- call ck_space ; check for space
- or cx, cx
- jz @@symbolend
- cmp al, CTRL_Z ; eof character?
- je @@symbolend
- cmp al, '('
- je @@symbolend
- cmp al, ')'
- je @@symbolend
- cmp al, ''''
- je @@symbolend
- cmp al, '`'
- je @@symbolend
- cmp al, COM
- je @@symbolend
- cmp al, ','
- je @@symbolend
- cmp al, '"'
- je @@symbolend
- cmp al, '['
- je @@symbolend
- cmp al, ']'
- je @@symbolend
- cmp al, '{'
- je @@symbolend
- cmp al, '}'
- je @@symbolend
- push bx
- lea bx, [hicases]
- xlat
- pop bx
- cmp al, '|'
- jne @@not@@escaped
- mov [@@escaped], 1
- call delimby C, ax ; read the whole symbol
- jnc @@symbolnext
- jmp @@bye
- @@not@@escaped:
- cmp al, '\'
- jne @@stillnot@@escaped
- mov [@@escaped], 1
- mov [flg_eof], 1
- call rcvchar
- jnc @@symbolok
- @@symbolerror:
- jmp @@bye ; if carry flag set, force exit
- @@symbolok:
- mov [flg_eof], 0
- @@stillnot@@escaped:
- call addchar C, bx, ax
- or ax, ax
- jnz @@symbolerror
- inc bx
- @@symbolnext:
- call rcvchar ; get the next character
- jc @@symbolerror
- jmp @@symbol
-
- @@symbolend:
- xor al, al ; put null at end of token
- call addchar C, bx, ax
- or ax, ax
- jnz @@symbolerror
-
- cmp bx, 1 ; Check for single, un@@escaped dot
- jne @@number
- cmp [BYTE si], '.'
- jne @@number
- cmp [@@escaped], 1
- je @@number
- jmp @@donenormal
- @@number: ; A token has been read, check for number
- push bx
- call scannum C, si, [@@numbase]
- mov si, [atomb]
- pop bx
- or ax, ax ; number or not?
- jnz @@thinkso
- jmp @@donecharorinterned
- @@thinkso:
- cmp [@@escaped], 1
- jne @@believeso
- jmp @@donecharorinterned
- @@believeso:
- or ax, ax ; floating-point ?
- jle @@floatingpoint
- add ax, 9 ; (ax + 9) / 2
- shr ax, 1 ; ax = bytes needed for integer
- mov [@@biglimit], ax ; save for later
- call malloc C, ax ; allocate memory for @@big
- or ax, ax
- jne @@numberok
- jmp @@memerr
- @@numberok:
- mov bx, ax
- mov [@@big], ax
- mov [WORD bx+3], 0
- call buildint C, bx, [atomb], [@@numbase]
- mov di, [main_reg]
- mov bx, [@@big]
- call alloc_int C, di, bx
- call free C, [@@big]
- jmp @@done
-
- @@floatingpoint:
- lea dx, [@@flo]
- call scanflo C, si, dx, [@@numbase]
- mov di, [main_reg]
- lea bx, [@@flo]
- call alloc_flonum C, di, [WORD bx], [WORD bx+2], [WORD bx+4], [WORD bx+6]
- jmp @@done
-
- @@donecharorinterned:
- cmp [@@char], 0 ; #\ macro?
- mov di, [main_reg]
- jne @@donechar
- jmp @@donesymbol
- @@donechar:
- mov [(REG di).page], SPECCHAR*2
- cmp bx, 1 ; only one character?
- jne @@multichar
- xor ah, ah
- mov al, [si]
- mov [(REG di).disp], ax
- jmp @@done
- @@multichar:
- mov al, [si]
- lea bx, [hicases]
- xlat
- mov [si], al
- xor bx, bx
- @@multiloop:
- cmp bl, SPECIALCHARS*2 ; finish the comparison?
- je @@multierror
- mov cx, bx
- mov di, [spchars+bx]
- xor bx, bx
- @@multianother:
- mov al, [di+bx+1] ; get the character in string
- cmp al, 0 ; end of string
- je @@multiend
- cmp [si+bx], al
- jne @@multinext
- inc bx
- jmp @@multianother
- @@multiend:
- mov al, [di]
- mov di, [main_reg]
- mov [(REG di).disp], ax
- jmp @@done
-
- @@multinext:
- mov bx, cx
- inc bx
- inc bx
- jmp @@multiloop
-
- @@multierror:
- mov di, [main_reg]
- mov [(REG di).disp], '?'
- mov [@@status], -1
- jmp @@done
-
- @@donesymbol:
- call intern C, di, si, bx
- jmp @@done
-
- @@donespecial:
- call intern C, di, si, bx
- lea bx, [nil_reg]
- mov di, [main_reg]
- call cons C, di, di, bx
- jmp @@bye
-
- @@donenormal:
- call intern C, di, si, bx
- lea bx, [nil_reg]
- mov di, [main_reg]
- call cons C, di, di, bx
- @@done:
- cmp [char], CTRL_Z ; EOF character?
- je @@bye
- call pushchar C ; put post-atom char back to buffer
- @@bye:
- call free C, [atomb] ; release memory
- mov [flg_eof], 1 ; reset flags
- mov [limit], 0
- mov ax, [@@status]
- @@ret:
- ret
- ENDP read_atom
-
- ;************************************************************************
- ; DELIMBY(c)
- ; DELIMBY takes characters from the input stream and places them
- ; in the buffer ATOMB, starting at offset stored in bx register, and
- ; ending when the delimiting character C is reached.
- ; Note: si = address of atomb
- ; bx = number of characters in atomb
- ;************************************************************************
- PROC C delimby, @@char:WORD
- mov [flg_eof], 1 ; signal the EOF error
- call rcvchar
- jc @@exit
- @@loop:
- cmp al, [BYTE @@char] ; reach the end?
- je @@done
- or al, al
- jz @@skip ; strings are null-terminated. we drop this
- cmp al, '\'
- jne @@notescaped
- call rcvchar
- jc @@exit
- @@notescaped:
- call addchar C, bx, ax
- or ax, ax
- jnz @@exit
- inc bx
- @@skip:
- call rcvchar
- jc @@exit
- jmp @@loop
- @@done:
- mov [flg_eof], 0
- @@exit:
- ret
- ENDP delimby
-
- ;************************************************************************
- ; ADDCHAR (i, c)
- ; ADDCHAR takes the character c and places it in the dynamic
- ; atom buffer atomb, at offset i. If the buffer can not contain
- ; any more characters, additional space is allocated, and limit
- ; is adjusted accordingly.
- ;************************************************************************
- PROC C addchar, @@index:WORD, @@char:WORD
- mov bx, [@@index]
- cmp bx, [limit]
- jl @@roomleft
-
- add [limit], BUFSIZE
- call realloc C, [atomb], [limit]
- or ax, ax
- jne @@memok
- mov ax, HEAPERR
- call abortread C, ax
- mov ax, -1 ; ax = -1 for error
- jmp @@ret
- @@memok:
- mov [atomb], ax
- mov si, ax
- mov bx, [@@index]
- @@roomleft:
- mov ax, [@@char]
- mov [si+bx], al
- xor ax, ax ; clear ax for success
- @@ret:
- ret
- ENDP addchar
-
- ;************************************************************************
- ; ABORTREAD(code)
- ; Cancels the entire read operation (should exit after it), after
- ; resetting some vital registers.
- ; Note: di = address of main register
- ;************************************************************************
- PROC C abortread, errcode:WORD
- mov di, [main_reg]
- cmp [errcode], EOFERR
- jne @@generic
- mov [(REG di).page], EOF_PAGE*2
- mov [(REG di).disp], EOF_DISP
- jmp @@done
-
- @@generic:
- xor ax, ax
- mov [(REG di).page], ax ; NUL main register
- mov [(REG di).disp], ax
- @@done:
- call errmsg C, [errcode]
- ret
- ENDP abortread
-
- ;**********************************************************************
- ; Local support to check the character in ax is space or not
- ; Note: cx = 0 iff the character is whitespace
- ;**********************************************************************
- PROC ck_space NEAR
- xor cx, cx
- cmp al, SPACE
- je @@yup
- cmp al, TAB
- jb @@nope
- cmp al, CR
- jbe @@yup
- @@nope:
- inc cx
- @@yup:
- ret
- ENDP ck_space
-
- END
-